/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package utilitarios;

import imagemYUV.novoFormato;
import java.io.IOException;
import java.util.ArrayList;

/**
 *
 * @author Mateus
 */
public class Compressao {

    public static novoFormato comprimi(novoFormato novo) {
        int cont = 0;
        //mantenho o Y intaquito
        int largura = Conversoes.byteArray2Int4(novo.largura);
        int altura = Conversoes.byteArray2Int4(novo.altura);
        byte[][] matrizYUV = new byte[altura][largura * 3];
        int somaU = 0;
        int somaV = 0;

        //transforma o vetor de yuv em uma matrizYUV
        for (int i = 0; i < altura; i++) {
            for (int j = 0; j < largura * 3; j++) {
                matrizYUV[i][j] = novo.imagem[cont];
                cont++;
            }
        }
        cont = 0;
        int deslocamento = 0;
        if ((largura % 4) != 0) {
            deslocamento = (4 - ((largura * 3) % 4));
        }        
        //compressao acontece aqui - vetor geral tem a metade do arquivo incial pois Ã© a imagem comprimida
        byte[] vetorGeral = null;
        
        if((largura) % 2 == 0 && altura % 2 == 0)
            vetorGeral = new byte[((largura*3)*altura)/2];
        
        if((largura) % 2 != 0 && altura % 2 == 0){
            int temp = (int)((altura * 3)/1.5);
            vetorGeral = new byte[((((largura*3)*altura) - (altura*3))/2) + temp];
        }
        
        if((largura) % 2 == 0 && altura % 2 != 0){
            int temp = (int)((largura * 3)/1.5);
            int matrizNormal = (((largura*3)*altura) - (largura*3))/2;
            vetorGeral = new byte[matrizNormal + temp];
        }
        
        if((largura) % 2 != 0 && altura % 2 != 0){
            int temp1 = (int)(((altura -1) * 3)/1.5);
            int temp2 = (int)(((largura -1) * 3)/1.5);
            int bytesMatizExata = (((largura - 1)*3)*(altura -1))/2;
            vetorGeral = new byte[(bytesMatizExata)+(temp1)+(temp2) + 4];
        }

        //caso a linha nÃ£o seja divisÃ­vel por 2 tem fazer media da ultima coluna com 2 pixeis
        if ((altura) % 2 != 0 || (largura ) % 2 != 0) {
            boolean ultimaLinha = false;
            boolean ultimaColuna = false;
            for (int i = 0; i < altura; i += 2) {
                ultimaColuna = false;
                for (int j = 0; j < largura * 3; j += 6) {
                    
                    if(j == ((largura * 3)-deslocamento)){
                        j += deslocamento;
                    }
                    
                    if (j == (largura * 3) - 3) {
                        if(ultimaLinha == true){
                            somaU += (matrizYUV[i][j + 1] & 0xFF);
                            somaV += (matrizYUV[i][j + 2] & 0xFF);
                            somaU += (matrizYUV[i][j + 1] & 0xFF);
                            somaV += (matrizYUV[i][j + 2] & 0xFF);
                            int auxU = somaU / 2;
                            int auxV = somaV / 2;
                            vetorGeral[cont] = (byte) (auxU);
                            vetorGeral[cont + 1] = (byte) (auxV);
                            vetorGeral[cont + 2] = matrizYUV[i][j];
                            vetorGeral[cont + 3] = matrizYUV[i][j];
                            j += 3;
                            somaU = 0;
                            somaV = 0;
                            break;
                        }
                        else{
                            somaU += (matrizYUV[i][j + 1] & 0xFF);
                            somaV += (matrizYUV[i][j + 2] & 0xFF);
                            somaU += (matrizYUV[i + 1][j + 1] & 0xFF);
                            somaV += (matrizYUV[i + 1][j + 2] & 0xFF);
                            int auxU = somaU / 2;
                            int auxV = somaV / 2;
                            vetorGeral[cont] = (byte) (auxU);
                            vetorGeral[cont + 1] = (byte) (auxV);
                            vetorGeral[cont + 2] = matrizYUV[i][j];
                            vetorGeral[cont + 3] = matrizYUV[i + 1][j];

                            somaU = 0;
                            somaV = 0;
                            cont += 4;
                            j += 3;
                            ultimaColuna = true;
                        }
                    }
                    if (i == altura - 1) {
                        somaU += (matrizYUV[i][j + 1] & 0xFF);
                        somaV += (matrizYUV[i][j + 2] & 0xFF);
                        somaU += (matrizYUV[i][j + 4] & 0xFF);
                        somaV += (matrizYUV[i][j + 5] & 0xFF);
                        int auxU = somaU / 2;
                        int auxV = somaV / 2;
                        vetorGeral[cont] = (byte) (auxU);
                        vetorGeral[cont + 1] = (byte) (auxV);
                        vetorGeral[cont + 2] = matrizYUV[i][j];
                        vetorGeral[cont + 3] = matrizYUV[i][j + 3];

                        somaU = 0;
                        somaV = 0;
                        cont += 4;
                        ultimaLinha = true;
                    }
                    
                    if(ultimaLinha == false && ultimaColuna == false){
                        somaU += (matrizYUV[i][j + 1] & 0xFF);
                        somaV += (matrizYUV[i][j + 2] & 0xFF);
                        somaU += (matrizYUV[i][j + 4] & 0xFF);
                        somaV += (matrizYUV[i][j + 5] & 0xFF);
                        somaU += (matrizYUV[i + 1][j + 1] & 0xFF);
                        somaV += (matrizYUV[i + 1][j + 2] & 0xFF);
                        somaU += (matrizYUV[i + 1][j + 4] & 0xFF);
                        somaV += (matrizYUV[i + 1][j + 5] & 0xFF);
                        int auxU = somaU / 4;
                        int auxV = somaV / 4;
                        vetorGeral[cont] = (byte) (auxU);
                        vetorGeral[cont + 1] = (byte) (auxV);
                        vetorGeral[cont + 2] = matrizYUV[i][j];
                        vetorGeral[cont + 3] = matrizYUV[i][j + 3];
                        vetorGeral[cont + 4] = matrizYUV[i + 1][j];
                        vetorGeral[cont + 5] = matrizYUV[i + 1][j + 3];

                        somaU = 0;
                        somaV = 0;
                        cont += 6;
                    }
                    

                }
            }
        }

        if ((altura) % 2 == 0 && (largura) % 2 == 0) {
            for (int i = 0; i < altura; i += 2) {
                for (int j = 0; j < largura * 3; j += 6) {
                    
                    if(j == ((largura * 3)-deslocamento)){
                        j += deslocamento;
                    }
                    
                    somaU += (matrizYUV[i][j + 1] & 0xFF);
                    somaV += (matrizYUV[i][j + 2] & 0xFF);
                    somaU += (matrizYUV[i][j + 4] & 0xFF);
                    somaV += (matrizYUV[i][j + 5] & 0xFF);
                    somaU += (matrizYUV[i + 1][j + 1] & 0xFF);
                    somaV += (matrizYUV[i + 1][j + 2] & 0xFF);
                    somaU += (matrizYUV[i + 1][j + 4] & 0xFF);
                    somaV += (matrizYUV[i + 1][j + 5] & 0xFF);
                    int auxU = somaU / 4;
                    int auxV = somaV / 4;
                    vetorGeral[cont] = (byte) (auxU);
                    vetorGeral[cont + 1] = (byte) (auxV);
                    vetorGeral[cont + 2] = matrizYUV[i][j];
                    vetorGeral[cont + 3] = matrizYUV[i][j + 3];
                    vetorGeral[cont + 4] = matrizYUV[i + 1][j];
                    vetorGeral[cont + 5] = matrizYUV[i + 1][j + 3];

                    somaU = 0;
                    somaV = 0;
                    cont += 6;
                }
            }
        }


        novo.isCompressed = 1;
        novo.imagemComprimida = vetorGeral;
        novo.imagem = null;

        return novo;
    }
}
